﻿namespace NebulaServer.Core
{    
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using NebulaServer.Config;

    public class MefComposition : IComposition
    {
        private IConfig config;
        private IEnumerable<string> pluginsPath;
        private AggregateCatalog aggregateCatalog;
        private CompositionContainer container;

        public void Compose(string pluginPath)
        {
            this.config = new ConfigQuery();
            this.aggregateCatalog = new AggregateCatalog();

            // get all sub-folder to find plugin dll
            var allDirectory = this.config.Get<string>("AllDirectory");
            this.pluginsPath = Directory.GetDirectories(pluginPath, allDirectory, SearchOption.TopDirectoryOnly);
            foreach (var path in this.pluginsPath)
            {
                this.aggregateCatalog.Catalogs.Add(new DirectoryCatalog(path));
            }

            var currentAssembly = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            this.aggregateCatalog.Catalogs.Add(currentAssembly);
            this.container = new CompositionContainer(this.aggregateCatalog);

            // retrieve all imports/exports in plugins and nebula server
            // and compose them
            var batch = new CompositionBatch();
            batch.AddPart(this.container);
            this.container.Compose(batch);
        }

        public T GetLazyExportValue<T>(string contractName) 
        {
            var lazyExport = this.container.GetExports<T>(contractName).FirstOrDefault();
            return lazyExport != null ? lazyExport.Value : default(T);
        }
    }
}